Навигация по странице:
1. malloc
• Массив
• Двумерный массив
2. calloc
3. realloc
• Массив
• Двумерный массив
4. Освобождение памяти
Иногда в задачах мы не знаем сколько элементов будет храниться в конкретном массиве. Поэтому применяют методы динамического выделения памяти.
Если мы хотим динамически выделить память, то используют функции malloc или calloc, или realloc, которые находятся в библиотеках <stdlib.h> и <malloc.h>. Давайте по порядку.
Навигация по странице:
1. malloc
• Массив
• Двумерный массив
2. calloc
3. realloc
• Массив
• Двумерный массив
4. Освобождение памяти
Чтобы выделить память с помощью malloc, нам нужно указать только размер в байтах. Для выделения 20 элементов массива типа int , нам понадобиться 80 байт, так как
один элемент типа int равен 4 байтам. Чтобы не считать сколько байт нам нужно выделить, используется
sizeof(тип данных), это значение будет равно одному элементу заданного типа.
Например, sizeof(int) будет равен 4 байтам.
Примеры выделения памяти под 20 элементов массива типа int:
int* a = malloc(80) или int* a = malloc(20 * sizeof(int))
Лучше использовать второй способ, с ним вы не совершите ошибку.
Функция malloc возвращает указатель на выделенное пространство или NULL, Если не находит место под память. Нужно помнить об этом и на всякий случай проверять.
Выделить те же 20 элементов под структуру point с именем p можно так:
struct point *p = malloc(20 * sizeof(struct point));
Чтобы динамически выделить память под двумерный массив, нужен массив указателей. Каждый элемент этого массива будет хранить адрес начала строки. Визуализировать такой способ можно так:
Сначала нужно выделить память под массив указателей, далее для каждого элемента массива указателей выделить строку размера m.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<stdio.h> #include<stdlib.h> #include<math.h> #include<malloc.h> int main() { int** a; int n, m, i, j; scanf_s("%i%i", &n, &m); a = malloc(n * sizeof(int*)); for (i = 0; i < n; i++) { a[i] = malloc(m * sizeof(int)); } for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { scanf_s("%i", &a[i][j]); a[i][j] += 100; } } for (i = 0; i < n; i++) { for (j = 0; j < m; j++) { printf("%i ", a[i][j]); } printf("\n"); } return 0; }
Для начала мы выделяем массив под указатели на строки. Посе чего, в цикле, для каждого элемента
массива a выделяем память под m элементов, функция malloc вернет в элемент a[i]
адрес строки i. Тем самым мы получаем массив указателей на строки. Теперь мы можем спокойно использовать эту память.
Для обращения к элементам можно использовать как a[i][j], так и *(*(a + i) + j).
Размеры каждой строки вы можете определять сами, что может быть полезно для некоторых задач.
Чтобы выделить память с помощью calloc нам нужны два аргумента: количество элементов и размер одного элемента. В отличии от malloc, который просто выделяет память, calloc
инициализирует все элементы массива нулями.
Пример выделения памяти под 20 элементов массива типа int:
int* a = calloc(20, sizeof(int))
С помощью realloc вы можете уменьшить размер массива или дополнительно выделить память под несколько элементов, если до этого массив был динамически выделен с помощью функций malloc или calloc, или realloc.
Чтобы выделить дополнительную память с помощью realloc, нужен, во-первых, указатель на прошлый массив, который был выделен динамически.
Во-вторых, указать новый размер массива, он может быть и меньше, тогда все элементы, которые выходят за границу справа, будут удалены.
Вот так выглядит выделение дополнительных двух элементов массива:
1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h> #include<stdlib.h> #include<malloc.h> int main() { int* array = malloc(1 * sizeof(int)); array[0] = 3; array = realloc(array, 3 * sizeof(int)); array[1] = 4; array[2] = 5; return 0; }
Выделение дополнительных 5 столбцов матрицы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h> #include<stdlib.h> #include<malloc.h> int main() { int** a; int n, m, i, j; scanf_s("%i%i", &n, &m); a = malloc(n * sizeof(int*)); for (i = 0; i < n; i++) { a[i] = malloc(m * sizeof(int)); } for (i = 0; i < n; i++) { a[i] = realloc(a[i], (m + 5) * sizeof(int)); } return 0; }
Теперь матрица размера n * (m + 5).
Конечно, для каждой строки вы можете добавить разное количество элементов, что может быть полезно для некоторых задач.
Выделение дополнительных 2 строк матрицы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h> #include<stdlib.h> #include<malloc.h> int main() { int** a; int n, m, i, j; scanf_s("%i%i", &n, &m); a = malloc(n * sizeof(int*)); for (i = 0; i < n; i++) { a[i] = malloc(m * sizeof(int)); } int l = n + 2; // l - новое кол-во строк a = realloc(a, (l) * sizeof(int*)); for (i = n; i < l; i++) { a[i] = malloc(m * sizeof(int)); } return 0; }
Теперь можем использовать элементы a[n][i] и a[n + 1][i]. Матрица имеет размер (n + 2) * m.
Выделять динамически память может быть очень полезным для решения задач. Например, в задачах про графы, где мы точно не знаем сколько путей из каждой вершины. Вы можете изучить алгоритмы DFS и BFS, где так же используется динамическое выделение памяти.
Чтобы освободить динамически выделенную память, применяют функцию free(указатель на массив).
Пример освобождения памяти для массива:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> #include<malloc.h> int main() { int* array = malloc(10 * sizeof(int)); for (int i = 0; i < 10; i++) { array[i] = i + 1; } for (int i = 0; i < 10; i++) { printf("%i ", array[i]); } free(array); return 0; }
Чтобы освободить память под двумерный массив, нужно сначала освободить память, выделенную под строки, а затем под массив указателей на строки.
Пример освобождения памяти для двумерного массива:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h> #include<stdlib.h> #include<malloc.h> int main() { int** a; int n, m, i, j; scanf_s("%i%i", &n, &m); a = malloc(n * sizeof(int*)); for (i = 0; i < n; i++) { a[i] = malloc(m * sizeof(int)); } for (i = 0; i < n; i++) { free(a[i]); } free(a); return 0; }
Code.C
© Copyright Павел Калашников 2021
обратная связь code.c04@mail.ru